package NetworkAdapter.Implementation; import EnvironmentPluginAPI.Exceptions.TechnicalException; import EnvironmentPluginAPI.CustomNetworkMessages.NetworkMessage; import ZeroTypes.Exceptions.ErrorMessages; import NetworkAdapter.Interface.Exceptions.ConnectionLostException; import NetworkAdapter.Interface.Exceptions.HostUnreachableException; import NetworkAdapter.Interface.Exceptions.NotConnectedException; import NetworkAdapter.Interface.IClientNetworkAdapter; import NetworkAdapter.Interface.MessageChannel; import NetworkAdapter.Messages.ClientAckMessage; import NetworkAdapter.Messages.ClientJoinMessage; import NetworkAdapter.Messages.ConnectionEndMessage; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.InvalidParameterException; class ClientNetworkAdapterUseCase extends AbstractNetworkAdapterUseCase implements IClientNetworkAdapter, NetworkChannel.NetworkMessageReceivedHandle<NetworkMessage> { private NetworkChannel controlChannel; private NetworkChannel dataChannel; private ClassLoader currentClassLoader; private boolean connected; private int clientId; public ClientNetworkAdapterUseCase() { connected = false; clientId = -1; } @Override public boolean isConnected() { return connected; } @Override public void connectToServer(String hostname, int port, String clientName) throws HostUnreachableException, InvalidParameterException, TechnicalException { InetAddress address; Socket socket; NetworkAccessProtocol protocol; try { //try to open the control port address = InetAddress.getByName(hostname); socket = new Socket(address, port); protocol = new NetworkAccessProtocol(socket); // say hello and wait for ack protocol.writeMessage(new ClientJoinMessage(-1, clientName)); NetworkMessage message = protocol.readMessage(); //if that is successful establish control channel and try to open data connection if (message instanceof ClientAckMessage) { clientId = message.getClientId(); controlChannel = new NetworkChannel<NetworkMessage>(protocol, this); if (currentClassLoader != null) { controlChannel.setContextClassLoader(currentClassLoader); } controlChannel.start(); socket = new Socket(address, port + 1); protocol = new NetworkAccessProtocol(socket); // say hello and wait for ack protocol.writeMessage(new ClientJoinMessage(clientId, clientName)); message = protocol.readMessage(); //if that worked, too, we can establish the data connection and are done if (message instanceof ClientAckMessage) { dataChannel = new NetworkChannel<NetworkMessage>(protocol, this); if (currentClassLoader != null) { dataChannel.setContextClassLoader(currentClassLoader); } dataChannel.start(); } else { // abort (we were so close..) :( throw new HostUnreachableException(); } } else { // else abort :( throw new HostUnreachableException(); } } catch (UnknownHostException e) { throw new HostUnreachableException(); } catch (IOException e) { throw new TechnicalException(ErrorMessages.get("networkError")); } catch (ConnectionLostException e) { throw new HostUnreachableException(); } connected = true; } @Override public int getClientId() throws NotConnectedException { if (!connected) { throw new NotConnectedException(); } return clientId; } @Override public synchronized void sendNetworkMessage(NetworkMessage message, MessageChannel channel) throws NotConnectedException, ConnectionLostException { if (channel == MessageChannel.DATA) { dataChannel.sendNetworkMessage(message); } else { controlChannel.sendNetworkMessage(message); } } @Override public void disconnect() { connected = false; try { ConnectionEndMessage bye = new ConnectionEndMessage(clientId, "clientDisconnecting"); controlChannel.sendNetworkMessage(bye); dataChannel.sendNetworkMessage(bye); } catch (ConnectionLostException e) { } //closing anyway } @Override public void setContextClassLoader(ClassLoader classLoader) { currentClassLoader = classLoader; if (controlChannel != null) { controlChannel.setContextClassLoader(classLoader); } if (dataChannel != null) { dataChannel.setContextClassLoader(classLoader); } } @Override public void handleMessage(NetworkMessage message) throws NotConnectedException, ConnectionLostException { if (!(message instanceof ConnectionEndMessage)) { informSubscribers(message); } else { dataChannel.forceClose(); controlChannel.forceClose(); } } @Override public void handleException(Exception exception) { } }